package com.hm.health.View.mpchart;

import android.graphics.Canvas;
import android.graphics.Paint;

import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.CircleBuffer;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.LineDataProvider;
import com.github.mikephil.charting.renderer.LineChartRenderer;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.goodix.comsdk.entity.Point;

import java.util.List;

/**
 * Created by chenshi on 2019/1/2.
 */

public class LineChartRenderEx extends LineChartRenderer{

    public LineChartRenderEx(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
        super(chart, animator, viewPortHandler);
    }

    /**
     * 只绘制大和最小的点
     * @param c
     */
    protected void drawCircles(Canvas c) {
        this.mRenderPaint.setStyle(Paint.Style.FILL);
        float phaseX = this.mAnimator.getPhaseX();
        float phaseY = this.mAnimator.getPhaseY();
        List<LineDataSet> dataSets = this.mChart.getLineData().getDataSets();

        for(int i = 0; i < dataSets.size(); ++i) {
            LineDataSet dataSet = dataSets.get(i);
            if(dataSet.isVisible() && dataSet.isDrawCirclesEnabled() && dataSet.getEntryCount() != 0) {
                this.mCirclePaintInner.setColor(dataSet.getCircleHoleColor());
                Transformer trans = this.mChart.getTransformer(dataSet.getAxisDependency());
                List<Entry> entries = dataSet.getYVals();
                Entry entryFrom = dataSet.getEntryForXIndex(this.mMinX < 0?0:this.mMinX);
                Entry entryTo = dataSet.getEntryForXIndex(this.mMaxX);
                int diff = entryFrom == entryTo?1:0;
                int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0);
                int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size());
                CircleBuffer buffer = this.mCircleBuffers[i];
                buffer.setPhases(phaseX, phaseY);
                buffer.limitFrom(minx);
                buffer.limitTo(maxx);
                buffer.feed(entries);
                trans.pointValuesToPixel(buffer.buffer);
                float halfsize = dataSet.getCircleSize() / 2.0F;
                int j = 0;

                Point<Float> max = new Point<>(Float.MIN_VALUE, Float.MIN_VALUE);
                Point<Float> min = new Point<>(Float.MAX_VALUE, Float.MAX_VALUE);
                int maxPos =0, minPos = 0;

                for(int count = (int)Math.ceil((double)((float)(maxx - minx) * phaseX + (float)minx)) * 2; j < count; j += 2) {
                    float x = buffer.buffer[j];
                    float y = buffer.buffer[j + 1];
                    if(!this.mViewPortHandler.isInBoundsRight(x)) {
                        break;
                    }

                    if (y > max.y) {
                        max.x = x;
                        max.y = y;
                        maxPos = j;
                    }

                    if (y < min.y) {
                        min.x = x;
                        min.y = y;
                        minPos = j;
                    }
                }

                drawCubic1(max,c,dataSet,halfsize,maxPos,minx);
                drawCubic1(min,c,dataSet,halfsize,minPos,minx);
            }
        }

    }

    private void drawCubic1(Point<Float> po, Canvas c, LineDataSet dataSet, float halfsize, int dataIndex, int minx) {
        float x = po.x;
        float y = po.y;
        if(this.mViewPortHandler.isInBoundsLeft(x) && this.mViewPortHandler.isInBoundsY(y)) {

            int circleColor = dataSet.getCircleColor(dataIndex / 2 + minx);
            this.mRenderPaint.setColor(circleColor);
            c.drawCircle(x, y, dataSet.getCircleSize(), this.mRenderPaint);
            if(dataSet.isDrawCircleHoleEnabled() && circleColor != this.mCirclePaintInner.getColor()) {
                c.drawCircle(x, y, halfsize, this.mCirclePaintInner);
            }
        }
    }

    /**
     * 只绘制最大和最小值
     * @param c
     */
    public void drawValues1(Canvas c) {
        if ((float) this.mChart.getLineData().getYValCount() < (float) this.mChart.getMaxVisibleCount() * this.mViewPortHandler.getScaleX()) {
            List<LineDataSet> dataSets = this.mChart.getLineData().getDataSets();

            for (int i = 0; i < dataSets.size(); ++i) {
                LineDataSet dataSet = dataSets.get(i);
                if (dataSet.isDrawValuesEnabled() && dataSet.getEntryCount() != 0) {
                    this.applyValueTextStyle(dataSet);
                    Transformer trans = this.mChart.getTransformer(dataSet.getAxisDependency());
                    int valOffset = (int) (dataSet.getCircleSize() * 1.75F);
                    if (!dataSet.isDrawCirclesEnabled()) {
                        valOffset /= 2;
                    }

                    List<Entry> entries = dataSet.getYVals();
                    Entry entryFrom = dataSet.getEntryForXIndex(this.mMinX);
                    Entry entryTo = dataSet.getEntryForXIndex(this.mMaxX);
                    int diff = entryFrom == entryTo ? 1 : 0;
                    int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0);
                    int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size());
                    float[] positions = trans.generateTransformedValuesLine(entries, this.mAnimator.getPhaseX(), this.mAnimator.getPhaseY(), minx, maxx);

                    Point<Float> max = new Point<>(Float.MIN_VALUE, Float.MIN_VALUE);
                    Point<Float> min = new Point<>(Float.MAX_VALUE, Float.MAX_VALUE);
                    int maxPos = 0, minPos = 0;

                    for (int j = 0; j < positions.length; j += 2) {
                        float x = positions[j];
                        float y = positions[j + 1];
                        if (!this.mViewPortHandler.isInBoundsRight(x)) {
                            break;
                        }

                        if (y > max.y) {
                            max.x = x;
                            max.y = y;
                            maxPos = j;
                        }

                        if (y < min.y) {
                            min.x = x;
                            min.y = y;
                            minPos = j;
                        }
                    }

                    if (this.mViewPortHandler.isInBoundsLeft(max.x) && this.mViewPortHandler.isInBoundsY(max.y)) {
                        Entry entry = entries.get(maxPos / 2 + minx);
                        this.drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, max.x, max.y - (float) valOffset);
                    }

                    if (this.mViewPortHandler.isInBoundsLeft(min.x) && this.mViewPortHandler.isInBoundsY(min.y)) {
                        Entry entry = entries.get(minPos / 2 + minx);
                        this.drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, min.x, min.y - (float) valOffset);
                    }
                }
            }
        }
    }
}
